
package br.com.iswe.gwt.crud.client;

import java.util.HashMap;
import java.util.Map;

import br.com.iswe.core.entidades.gwt.RemoteEntityObject;
import br.com.iswe.gwt.ui.client.Listener;

import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.Widget;


/**
 *
 * Description: This abstract class provides the CRUD Pattern for the
 * 				screen that needs to:
 * 				C - Create
 * 				R - Read (Search)
 * 				U - Update
 * 				D - Delete 
 * 				a given entity.
 * 
 * It provides this standard functionality by using a tabbar and diaplaying the search and detail screeen simultaniusly.
 *
 * @author Rafael Noronha de Almeida
 *
 * @version $Revision: 1.2 $ $Date: 2009/07/22 09:03:07 $
 *
 */
public abstract class CrudPanel<E extends RemoteEntityObject> extends Composite {

	public CrudPanel(){}
	
	protected int previusSelectedTab = 0;
	protected int tabLimit = 6;
	protected Map<E, Widget> tabToIdMap = new HashMap<E, Widget>();
	
	@SuppressWarnings("unchecked")
	protected void configScrenn() {
		//Listener para qdo um registro for selecionado na lista
		getSearchPanel().onSelectListener.add(new Listener<E>(){
			public void execute(E entity) {
				//Ao selecionar um item na lista detalha o registro
				detail(entity);
			}});
		
		getTabPanel().addBeforeSelectionHandler(new BeforeSelectionHandler<Integer>(){
			public void onBeforeSelection(BeforeSelectionEvent<Integer> event ) {
				//antes de mudar pega o id ta tab q estava selecionada antes
				previusSelectedTab = getTabPanel().getTabBar().getSelectedTab();
			}
		});
	}

	protected void detail(E entity){
		DetailPanelContract<E> detailPanel = beforeDetail( entity );
		String tabTitle = getTabTitle( entity );
		Label lbNewTab = new Label(" :: " + tabTitle);
		//verifica se ja existia uma tab para esse registro
		Widget previusTab = (Widget)tabToIdMap.remove(entity);
		if(previusTab != null){
			//remove a tab
			getTabPanel().remove(previusTab);
		}
		int tabId = addNewTab(detailPanel, lbNewTab);
		//armazena o id da tab
		Widget newTab = getTabPanel().getWidget(tabId);
		tabToIdMap.put(entity, newTab);//coloca no map para verificar posteriormente
		//configura os listener da tela de detail que afetam o painel externo do CRUD
		configDetailListeners(lbNewTab, detailPanel);
		//seleciona a tab q acabou de ser criada
		getTabPanel().selectTab(tabId);
	}
	
	protected abstract String getTabTitle(E entity);

	protected int addNewTab(DetailPanelContract<E> detailPanel, Label lbNewTab) {
		int tabId = getTabPanel().getWidgetCount();
		
		//verifica se o numero de tab exedeu o limite caso tenha exedido 
		//sempre remove a tab na posicao 1 antes de criar a nova
		if(tabId >= tabLimit){
			getTabPanel().remove(1);
			tabId = getTabPanel().getWidgetCount();
		}
		
		getTabPanel().insert((Widget)detailPanel, lbNewTab, tabId);
		
		return tabId;
	}
	
	protected void prepareInsert(){
		//prepara a tela para inclusao de um novo registro
		DetailPanelContract<E> detailPanel = beforeInsert();
		detailPanel.prepareInsert();
		
		//
		String title = getTabTitle(null);
		Label lbNewTab = new Label(" :: " + title);
		//lbNewTab.removeStyleName("gwt-Label");
		
		int tabId = addNewTab(detailPanel, lbNewTab);
		
		//configura os listener da tela de detail que afetam o painel externo do CRUD
		configDetailListeners(lbNewTab, detailPanel);
		
		//seleciona a tab q acabou de ser criada
		getTabPanel().selectTab(tabId);
	}

	protected void configDetailListeners(final Label lbNewTab, final DetailPanelContract<E> detailPanel) {
		//Evento ao clicar no botao cancelar
		detailPanel.addCancelListener(new Listener<DetailPanelContract<E>>(){
			public void execute(DetailPanelContract<E> detailPanel) {
				closeSelectedTab();
			}
		});
		
		//Evento apos salvar
		detailPanel.addAfterSaveListener(new Listener<DetailPanelContract<E>>(){
			public void execute(DetailPanelContract<E> detailPanel) {
				E entity = detailPanel.getEntity();
				//apos salvar garante que o name da tab mostre o login do usuario
				String tabTitle = getTabTitle( entity );
				lbNewTab.setText(" :: " + tabTitle + " :: ");
			}});
		
		//evento apos deletar
		detailPanel.addAfterDeleteListener(new Listener<DetailPanelContract<E>>(){
			public void execute(DetailPanelContract<E> detailPanel) {
				//execute the last search again
				getSearchPanel().getListPanel().search();
				closeSelectedTab();
			}
		});
	}
	
	protected void closeSelectedTab() {
		//Remove a tab q esta sendo mostrada no momento
		//tabPanel.remove(tabId);
		int selectedTab = getTabPanel().getTabBar().getSelectedTab();
		getTabPanel().remove(selectedTab);
		
		//verifica se a tab q esta selecionada antes possui um indica acima do indice q esta sendo removido,
		//caso seja acima e necessario subtrair 1 do valor 
		if(previusSelectedTab > selectedTab){
			previusSelectedTab--;
		}
		else if(previusSelectedTab == selectedTab || previusSelectedTab < 0){
			previusSelectedTab = 0;
		}
		
		//seleciona a tab q estava selecionada antes dessa tab fechar
		getTabPanel().selectTab(previusSelectedTab);
	}
	
	protected abstract DetailPanelContract<E> beforeDetail(E entity);
	
	protected abstract DetailPanelContract<E> beforeInsert();
	
	protected abstract TabPanel getTabPanel();

	protected abstract SearchPanel<E> getSearchPanel();
	
}
